#include <EEPROM.h>
#include <TimeAlarms.h>
#include <Time.h>
#include <ERxPachube.h>
#include <HomeEasy.h>
#include <Ethernet.h>
#include <SPI.h> 
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EthernetUdp.h>
#include <stdio.h>
#include <string.h>
#include <DS1302.h>
//#include <Mirf.h>
//#include <nRF24L01.h>
//#include <MirfHardwareSpiDriver.h>

#define heatingrealy 39
#define relay2realy 38
boolean receivingdata = false;

#define DEBUG
/* Set the appropriate digital I/O pin connections */
uint8_t CE_PIN   = 32;
uint8_t IO_PIN   = 31;
uint8_t SCLK_PIN = 30;

///%%**%%%%**%%%%**%%%%**%%%%**%%%%**%% ETHERNET STUFF %%**%%%%**%%%%**%%%%**%%%%**%%%%**%%/
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 
  10, 0, 0, 177 };
byte gw[] = { 
  10, 0, 0, 2 };
byte subnet[] = { 
  255, 255, 255, 0 };
byte powerAddr[] = {
  10,0,0,178}; // ip address to ping
byte clockAddr[] = {
  10,0,0,42}; // ip address to ping

EthernetServer server(355);
EthernetServer webserver(80);
IPAddress timeServer(91, 220, 127, 250 ); // time.nist.gov NTP server
IPAddress POWER(10,0,0,178);
IPAddress CLOCK(10,0,0,42);
EthernetClient clockclient;

int pachubestatus;
int pachubeinstatus;
float volts;
float watts;
float presses;
int SETTEMPaddr = 0;
int connecttimer = 0;
int connecttimer2 = 0;
boolean AlarmState = false;

DS1302 rtc(CE_PIN, IO_PIN, SCLK_PIN);

String Serialbits;
String Serialbits2;
boolean heatingAV = true;
#define BUFSIZ 100

int myCode = 0000000;
int myCode2 = 000000;
int heatingstate = 0;
int relay2state = 0;
int inheatingtime =0;

int enablePower=0;
boolean gettxt = false;
String CMD;
boolean firstmail = false;

byte SET_TEMP;
String txtMsg = "";                         // a string for incoming text
int lastStringLength = txtMsg.length();     // previous length of the String

void(* resetFunc) (void) = 0; //declare reset function @ address 0

#define PACHUBE_API_KEY	"u6QqiWp60s3YxcK7fLhZ3EQBgoWSAKxRV3RjSTlxNmJRWT0g" // fill in your API key PACHUBE_API_KEY      
#define PACHUBE_FEED_ID 49966 // fill in your feed id

#define POWER_PACHUBE_API_KEY "4aClJdo4LSlr3c41vmCBYcSO9hmSAKxEaHJ6bXVPTWYwYz0g" // fill in your API key PACHUBE_API_KEY
#define POWER_PACHUBE_FEED_ID 50468

ERxPachubeDataOut dataout(PACHUBE_API_KEY, PACHUBE_FEED_ID);
ERxPachubeDataOut dataout2(POWER_PACHUBE_API_KEY, POWER_PACHUBE_FEED_ID);

void PrintDataStream(const ERxPachube& pachube);
ERxPachubeDataIn datain(POWER_PACHUBE_API_KEY, POWER_PACHUBE_FEED_ID);
ERxPachubeDataIn datain2(PACHUBE_API_KEY, PACHUBE_FEED_ID);

HomeEasy homeEasy;

const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 
// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
unsigned int localPort = 8888;      // local port to listen for UDP packets
struct Alarm {
  int hour[4];
  int minute[4];
  int second[4];
} 
alarm = { 
  0, 0, 0 };

#define ONE_WIRE_BUS 22
#define ONE_WIRE_BUS2 23
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
OneWire oneWire2(ONE_WIRE_BUS2);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
DallasTemperature sensors2(&oneWire2);
// arrays to hold device address
DeviceAddress insideThermometer;

struct Timing {
  unsigned long current;
  unsigned long previous;
  unsigned long power;
  unsigned long sensor;
  unsigned long temps;
  unsigned long checkheating;
  unsigned long emailresend;
  unsigned long sendtemp;
  unsigned long sendpower;
  int delta;
} 
time = { 
  0, 0, 0, 0, 0, 0, 0, 0, 0};

struct Temps {
  DeviceAddress address;
  float temp;
} 
temps = { 
  0, 0};
Temps NewTemp[100];

struct Zone {
  String Name;
  int State;
  int Count;
  int Pin;
  int Prev;
  int Eepromadd;
  int Active;
  long Lasttrig;
  int Room[3];
  boolean Trigsent;
} 
zone = { 
  0, 0, 0 ,0 ,0 ,2 ,0, 0, 0, false};
Zone Zones[4];

void setup() {
  Serial.begin(115200);
  homeEasy = HomeEasy();
  homeEasy.init();
  rtc.write_protect(false);
  rtc.halt(false);
  SET_TEMP = EEPROM.read(SETTEMPaddr);
  pinMode(heatingrealy,OUTPUT);
  digitalWrite(heatingrealy,HIGH);
  pinMode(relay2realy,OUTPUT);
  digitalWrite(relay2realy,HIGH);  
  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  pinMode(10, OUTPUT);                       // set the SS pin as an output (necessary!)
  digitalWrite(10, HIGH);                    // but turn off the W5100 chip!

  //  Mirf.spi = &MirfHardwareSpi;
  //  Mirf.init();
  //  Mirf.setRADDR((byte *)"controller");
  //  Mirf.channel = 90;
  //  Mirf.config();

  // Debugging complete, we start the server!
  Ethernet.begin(mac,ip,subnet,gw);
  server.begin();
  webserver.begin();
  sensors.begin();
  sensors2.begin();
  Serial.print("Found ");
  Serial.print(sensors2.getDeviceCount(), DEC);
  Serial.println(" devices.");
  // report parasite power requirements
  Serial.print("Parasite power is: "); 
  if (sensors2.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");
  //  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0"); 

  dataout2.addData(0);
  dataout2.addData(1);
  dataout2.addData(2);

  dataout.addData(100);
  dataout.addData(99);
  for(int i=0;i<4;i++){
    int datas = i + 20;
    dataout.addData(datas);
  }

  int Devices = sensors2.getDeviceCount() + sensors.getDeviceCount()-1;
  for(int i=0; i< Devices; i++){
    dataout.addData(i);
    DeviceAddress tmpadd;
    sensors2.getAddress(tmpadd, i);
    Serial.print("Device ");
    Serial.print(i);
    Serial.print(" Address: ");
    printAddress(tmpadd);
    Serial.println();
    sensors2.setResolution(tmpadd, 9);
    Serial.print("Device ");
    Serial.print(i);
    Serial.print(" Resolution: ");
    Serial.print(sensors2.getResolution(tmpadd), DEC); 
    Serial.println();
  }
  sendRF(myCode,1,true,false);
  delay(3000);
  sendRF(myCode,1,false,false);

  Udp.begin(localPort);
  //  getNtpTime();
  synTime();
  loadtimers();
  INITAlarm();
  Serial.print("<p>Current Time: ");
  Serial.print(hour());
  Serial.print(":");
  Serial.print(minute());
  Serial.print(":");
  Serial.print(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print("/");
  Serial.print(month());
  Serial.print("/");
  Serial.println(year()); 
}

void loop()
{
  time.current = millis();
  time.delta = (int) (time.current - time.previous);
  time.previous = time.current;

  //  byte data[100]="";
  //  while(Mirf.dataReady()){
  //    String DispData="";
  //    Mirf.getData(data);
  //    for(int g =0;g<sizeof(data);g++){
  //
  //      if(String((char)data[g]) == "*"){
  //        receivingdata = true; 
  //        continue;
  //      }
  //      if(String((char)data[g]) == "#"){
  //        receivingdata = false; 
  //        continue;
  //      }
  //      if (receivingdata){
  //        DispData += char(data[g]);
  //        //        Serial.print(char(data[g]));
  //      }
  //    }
  //
  //    ProcessWiFly(DispData);
  //
  //  }
  //

#if defined(DEBUG)
  Serial.print("**************************** ");
  Serial.println(millis() / 1000);
#endif
  char clientline[BUFSIZ];
  int index = 0;

  CheckZones();

  //  if(time.current > (time.sendtemp + 30000)) { // 5 mins
  //Serial.println("Sending Temps");
  //sendTemps();  
  //    time.sendtemp = time.current;
  //  }
  if(time.current > (time.checkheating + 60000)) { // 5 mins
#if defined(DEBUG)
    Serial.println("Checking Heating");
#endif
    CheckHeating();
    time.checkheating = time.current;
  }

  if(time.current > (time.sensor + 40000)) { // 5 mins
#if defined(DEBUG)
    Serial.println("Getting Temps");
#endif
    sensors.requestTemperatures(); // Send the command to get temperatures
    sensors2.requestTemperatures(); // Send the command to get temperatures
    GetTemps();
    updatepachube();
    time.sensor = time.current;
  }

  //  if(time.current > (time.power + 10000)) { // 5 seconds
  //  #if defined(DEBUG)
  //      Serial.println("Updating Power");
  //#endif
  //    if(enablePower = 1){
  //      ICMPPing ping(pingSocket);
  //      ping(1, pingAddr, buffer);
  //#if defined(DEBUG)
  //      Serial.println(buffer);
  //#endif
  //
  //      if (buffer == "Request Timed Out"){
  //      }
  //      else{
  //        pachubeinstatus = datain.syncPachube();
  //        watts = convint(datain.getValueByIndex(0));
  //        volts = convint(datain.getValueByIndex(1));
  //      }
  //    }
  //    time.power = time.current;
  //  }

  //  float tempC = sensors.getTempC(insideThermometer);



  //if(time.current > (time.sendpower + 10000)) { // 5 mins
  // if (clockclient.connect(CLOCK, 2000)) {
  //    Serial.println("connected");
  //  } 
  //  else {
  //    // if you didn't get a connection to the server:
  //    Serial.println("connection failed");
  //  }
  //  
  //  if (clockclient.connected()) {
  //      clockclient.print("power,"); 
  //      clockclient.print(watts);
  //      clockclient.println(",");
  //    }
  //    clockclient.stop();
  //    time.sendpower = time.current;
  //}
  EthernetClient webclient = webserver.available();
  if (webclient) {

    boolean current_line_is_blank = true;

    // reset the input buffer
    index = 0;

    while (webclient.connected()) {
      if (webclient.available()) {
        char c = webclient.read();
        // If it isn't a new line, add the character to the buffer
        if (c != '\n' && c != '\r') {
          clientline[index] = c;
          index++;
          // are we too big for the buffer? start tossing out data
          if (index >= BUFSIZ) 
            index = BUFSIZ -1;

          // continue to read more data!
          continue;
        }

        // got a \n or \r new line, which means the string is done
        clientline[index] = 0;

        // Print it out for debugging
        //        Serial.println(clientline);

        // Look for substring such as a request to get the root file
        if (strstr(clientline, "GET / ") != 0) {


          // send a standard http response header
          webclient.println("HTTP/1.1 200 OK");
          webclient.println("Content-Type: text/html");
          webclient.println();
          webclient.println("<html><head><title> Malyon House Controller</title></head>");
          webclient.println("<body bgcolor=\"Black\"><font color=\"White\">");
          webclient.print("<h1><center>Welcome to Malyon Home Controller</center></h1><br>");
          webclient.print("<p>Current Time: ");
          webclient.print(hour());
          webclient.print(":");
          webclient.print(minute());
          webclient.print(":");
          webclient.print(second());
          webclient.print(" ");
          webclient.print(day());
          webclient.print("/");
          webclient.print(month());
          webclient.print("/");
          webclient.print(year()); 
          webclient.println("<BR>");
          webclient.print("Set Temp: ");
          webclient.print(SET_TEMP);
          webclient.println("<br>");
          webclient.print("Heating Time: ");
          webclient.println(inheatingtime);
          webclient.print("<br>Heating State: ");
          if(heatingstate == 1){
            webclient.println("On");            
          }
          else{
            webclient.println("Off");                        
          }
          webclient.print("<br>relay2 State: ");
          if(relay2state == 1){
            webclient.println("On");            
          }
          else{
            webclient.println("Off");                        
          }
          webclient.print("<br>Volts: ");
          webclient.print(volts);
          webclient.println("<br>Watts: ");
          webclient.print(watts);
          webclient.print("<br> Runtime (Seconds): ");
          webclient.println(millis() / 1000);
          webclient.print("<br>Pachube Update Status Code: ");
          webclient.println(pachubestatus);
          webclient.print("<br><br>");
          webclient.print("House Temps:-<br>");
          int Devices = sensors2.getDeviceCount() + sensors.getDeviceCount()-1;
          for(int i=0; i< Devices; i++){
            if( i == 5){
              continue; 
            }
            webclient.print("Sensor ");
            webclient.print(i);
            webclient.print(": ");
            webclient.print(NewTemp[i].temp);
            webclient.print("<BR>");
          }
          webclient.print("House Average Temp: ");
          webclient.print(CalcAvTemp());
          webclient.print("<br>Hot Water Temp: ");
          webclient.print(NewTemp[5].temp);
          webclient.print("<br>Boiler Room Temp: ");
          webclient.print(NewTemp[99].temp);
          webclient.println("<BR><br>");
          webclient.print("Alarm Status: ");
          if (AlarmState){
            webclient.print("Active<br>");            
          }
          else{
            webclient.print("Inactive<br>");                        
          }
          for(int i=0;i<4;i++){
            if(Zones[i].Active == 1){
              webclient.print("Zone ");
              webclient.print(Zones[i].Name);
              webclient.print(" State: ");
              webclient.print(Zones[i].State);
              webclient.print(" Trigger Count: ");
              webclient.print(Zones[i].Count);
              webclient.print(" Last Trigger: ");
              webclient.print(Zones[i].Lasttrig);              
              webclient.print(" Trigger Sent: ");
              webclient.print(Zones[i].Trigsent);              
              webclient.println("<BR><br>");
            }            
          }

          webclient.print("Amp Output:- <br>");
          webclient.print(Serialbits);
          webclient.println("<BR>");
          webclient.print("<br><br>SkyBox Info:- <br>");
          webclient.println(Serialbits2);
          webclient.println("</p></font></body></html>");
          //          updatepachube();
          break;
        } 
        else if (strstr(clientline, "GET /") != 0) {
          // this time no space after the /, so a sub-file!
          char *CMD;

          CMD = clientline + 5; // look after the "GET /" (5 chars)
          // a little trick, look for the " HTTP/1.1" string and 
          // turn the first character of the substring into a 0 to clear it out.
          (strstr(clientline, " HTTP"))[0] = 0;

          webclient.println("HTTP/1.1 200 OK");
          webclient.println("Content-Type: text/html");
          webclient.println();
          // print the file we want
          ProcessWiFly(CMD);
          webclient.println(CMD);
          break;
        }

      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    webclient.stop();
    GetTemps();
  }



  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (c == '@')
        {
          gettxt = true;
          txtMsg = ""; 
          continue;
        }
        if (c == '*')
        {
          client.stop();
        }
        if (c == '\\')
        {
          client.println("ThankYou");
          ProcessWiFly(txtMsg);
          txtMsg = ""; 
          gettxt = false;
        }
        else
        {
          if(gettxt){
            txtMsg += c;
          }
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
  Alarm.delay(0);
}


// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}
void sendRF(unsigned long lSender,unsigned int iRecipient, boolean bOn,boolean bGroup){
  homeEasy.sendAdvancedProtocolMessage(lSender,iRecipient,bOn,bGroup);
  homeEasy.sendAdvancedProtocolMessage(lSender,iRecipient,bOn,bGroup);
  homeEasy.sendAdvancedProtocolMessage(lSender,iRecipient,bOn,bGroup);
}




void updatepachube(){
#if defined(DEBUG)
  Serial.println("Updating Pachube");
#endif
  dataout.updateData(100, String(millis() /1000));
  dataout.updateData(99, NewTemp[99].temp);

  for(int i=0;i<4;i++){
    int datas = i + 20;
    dataout.updateData(datas, Zones[i].Count);
  }

  int Devices = sensors2.getDeviceCount() + sensors.getDeviceCount()-1;
  for(int i=0; i< Devices; i++){
    if(NewTemp[i].temp == 85){
    }
    else if (NewTemp[i].temp < -85){
    }
    else{
      dataout.updateData(i, NewTemp[i].temp);
    }
  }

  dataout2.updateData(0, watts);
  dataout2.updateData(1, volts);
  dataout2.updateData(2, presses);  
  dataout2.updatePachube();    

  pachubestatus = dataout.updatePachube();    

}
int convint(String Data){
  char carray2[Data.length() +1];
  Data.toCharArray(carray2,sizeof(carray2));
  return atoi(carray2); 
}

void ProcessWiFly(String Data){
  int i, count; 
  for (i=0, count=0; Data[i]; i++) 
    count += (Data[i] == ','); 

  String newData[count];

  for(int i =0; i < count;i++){
    int firstpos = Data.indexOf(",");
    newData[i] = Data.substring(0,firstpos);
    Data = Data.substring(firstpos+1,Data.length());
  }

  if(newData[0] == "power"){
    watts = convint(newData[1]);
    volts = convint(newData[2]);
    presses = convint(newData[3]);
  }

  if(newData[0] == "clearzonecount"){
    Zones[convint(newData[1])].Count = 0;
    EEPROM.write(Zones[convint(newData[1])].Eepromadd,0); 
  }
  if(newData[0] == "clearallzonecount"){
    for (int i = 0; i<4; i++){
      Zones[i].Count = 0;
      EEPROM.write(Zones[i].Eepromadd,0); 
    }
  }
  if(newData[0] == "alarmstate"){
    if(convint(newData[1]) == 1){
      AlarmState = true;
    }
    else if(convint(newData[1]) == 0){
      AlarmState = false;      
    }
  }
  if(newData[0] == "reboot"){
    server.println("Rebooting...");
    resetFunc();   
  }
  if(newData[0] == "relay2"){
      if(convint(newData[1]) == 1){
        relay2On();
      }
      if(newData[1] == 0){
        relay2Off();
      }        
  }
  if(newData[0] == "amp"){
    Serial3.println(newData[1]);
  }
  if(newData[0] == "getntp"){
    getNtpTime();
  }  
  if(newData[0] == "heating"){
    if(newData[1] == "state"){
      server.println(heatingstate); 

    }
    if(newData[1] == "rf"){
      boolean lstate=false;



      if (convint(newData[2]) == 1){
        lstate=true;
        HeatingOn();
      } 
      else {
        lstate=false;
        HeatingOffT();
      }


      //    sendRF(7,0,lstate,0); 
      server.print("Heating State: ");
      server.println(lstate);

    }
    if(newData[1] == "temp"){
      if(newData[2] == "set"){
        SET_TEMP = convint(newData[3]);
        EEPROM.write(SETTEMPaddr,SET_TEMP);
        //        lcd.clear();  

        server.print("Set to: ");
        server.println(SET_TEMP); 
      }
      if(newData[2] == "get"){
        float tempC = sensors.getTempC(insideThermometer);
        // server.print("Temp C: ");
        server.println(tempC); 
      }
    }

  }
    if(newData[0] == "time"){
          if(newData[1] == "set"){
      
      //    Time t2(year(t), month(t), day(t), hour(t), minute(t), second(t), weekday(t));
//    Time t2(convint(newData[6]), convint(newData[5]), convint(newData[5]), convint(newData[2]), convint(newData[3]), convint(newData[4]), convint(newData[7]));
  Time t(2013, 6, 7, 00, 22, 00, 5);
    rtc.write_protect(false);
  rtc.halt(false);

    rtc.time(t);
    synTime();   
          }
    }
  if(newData[0] == "lights"){
    boolean lstate=false;
    boolean gstate=false;


    if (convint(newData[3]) == 1){
      lstate=true;
    } 
    else {
      lstate=false;
    }

    if (convint(newData[4]) == 1){
      gstate=true;
    } 
    else {
      gstate=false;
    }
    server.print("Light Set to: ");
    server.println(lstate);
    sendRF(convint(newData[1]),convint(newData[2]),lstate,gstate); 

  }

}

void FishTankOn(){
  sendRF(2,0,1,0); 
}
void FishTankOff(){
  sendRF(2,0,0,0);
}

void HeatingOnT(){
  inheatingtime = 1;
  HeatingOn();
}

void relay2On(){
      digitalWrite(relay2realy,LOW);
      relay2state = 1;
}

void relay2Off(){
      digitalWrite(relay2realy,HIGH);
      relay2state = 0;
}


void HeatingOn(){
  float tempC = sensors.getTempC(insideThermometer);
  if( tempC < SET_TEMP){
//    sendRF(7,0,1,0); 
    digitalWrite(heatingrealy,LOW);
    //    Serial.println("Heating On");   
    heatingstate = 1;
  }
}
void HeatingOff(){
//  sendRF(7,0,0,0); 
  digitalWrite(heatingrealy,LOW);  
  //  Serial.println("Heating Off");    
  heatingstate = 0;
}
void HeatingOffT(){
  digitalWrite(heatingrealy,HIGH);  
//  sendRF(7,0,0,0); 
  //  Serial.println("Heating Off");    
  heatingstate = 0;
  inheatingtime = 0;
}
void CheckHeating(){
  if(inheatingtime == 1){

    if (heatingAV){
      if( CalcAvTemp() > SET_TEMP){
        HeatingOff();
        heatingstate = 0;
      }
      else if(CalcAvTemp() < SET_TEMP){
        HeatingOn();
        heatingstate = 1;
      }
    }
    else{
      float tempC = sensors.getTempC(insideThermometer);
      if( tempC > SET_TEMP && heatingstate ==1){
        HeatingOff();
        heatingstate = 0;
      }
      else if( tempC < SET_TEMP){
        HeatingOn();
        heatingstate = 1;
      }
    }
  }
  else 
  {
    if(heatingstate == 1){
      if (heatingAV){
        if( CalcAvTemp() > SET_TEMP){
          HeatingOff();
          heatingstate = 0;
        }
      }
      else{
        float tempC = sensors.getTempC(insideThermometer);
        if( tempC > SET_TEMP){
          HeatingOff();
          heatingstate = 0;
        }
      }
    }
  }
}
void Reboot(){
  resetFunc();
}
void loadtimers(){
  //  Alarm.alarmRepeat(dowSunday,03,30,0, getNtpTime);  

  Alarm.alarmRepeat(17,35,00, FishTankOn);  // 17:35am every day
  Alarm.alarmRepeat(23,59,00, FishTankOff);  // 23:59am every day

////relay2 
//  Alarm.alarmRepeat(7,12,00, relay2On);  // 07:12am every day
//  Alarm.alarmRepeat(9,12,00, relay2Off);  // 09:12am every day
//  Alarm.alarmRepeat(22,12,00, relay2On);  // 22:12pm every day
//  Alarm.alarmRepeat(23,12,00, relay2Off);  // 23:12pm every day
//  
  //Heating on Timers  
  Alarm.alarmRepeat(dowMonday,6,30,00, HeatingOnT);  
  Alarm.alarmRepeat(dowTuesday,6,30,00, HeatingOnT);    
  Alarm.alarmRepeat(dowWednesday,6,30,00, HeatingOnT);  
  Alarm.alarmRepeat(dowThursday,6,30,00, HeatingOnT);  
  Alarm.alarmRepeat(dowFriday,6,30,00, HeatingOnT);    
  Alarm.alarmRepeat(dowSaturday,6,30,00, HeatingOnT);    
  Alarm.alarmRepeat(dowSaturday,12,30,00, HeatingOnT);      
  Alarm.alarmRepeat(dowSunday,6,30,00, HeatingOnT);    
  Alarm.alarmRepeat(dowSunday,12,30,00, HeatingOnT);  
  Alarm.alarmRepeat(dowMonday,17,30,00, HeatingOnT);  
  Alarm.alarmRepeat(dowTuesday,17,30,00, HeatingOnT);    
  Alarm.alarmRepeat(dowWednesday,17,30,00, HeatingOnT);  
  Alarm.alarmRepeat(dowThursday,17,30,00, HeatingOnT);  
  Alarm.alarmRepeat(dowFriday,17,30,00, HeatingOnT);    
  Alarm.alarmRepeat(dowSaturday,17,30,00, HeatingOnT);    
  Alarm.alarmRepeat(dowSunday,17,30,00, HeatingOnT);    
  //End of Heating on Timers  

  //Heating off Timers  
  Alarm.alarmRepeat(dowMonday,8,00,00, HeatingOffT);    
  Alarm.alarmRepeat(dowTuesday,8,00,00, HeatingOffT);    
  Alarm.alarmRepeat(dowWednesday,8,00,00, HeatingOffT);    
  Alarm.alarmRepeat(dowThursday,8,00,00, HeatingOffT);    
  Alarm.alarmRepeat(dowFriday,8,00,00, HeatingOffT);    
  Alarm.alarmRepeat(dowSaturday,8,00,00, HeatingOffT);    
  Alarm.alarmRepeat(dowSunday,8,00,00, HeatingOffT);    
  Alarm.alarmRepeat(dowSaturday,14,30,00, HeatingOffT);    
  Alarm.alarmRepeat(dowSunday,14,30,00, HeatingOffT);   
  Alarm.alarmRepeat(dowMonday,20,31,00, HeatingOffT);    
  Alarm.alarmRepeat(dowTuesday,20,31,00, HeatingOffT);    
  Alarm.alarmRepeat(dowWednesday,20,31,00, HeatingOffT);    
  Alarm.alarmRepeat(dowThursday,20,31,00, HeatingOffT);    
  Alarm.alarmRepeat(dowFriday,20,31,00, HeatingOffT);    
  Alarm.alarmRepeat(dowSaturday,20,31,00, HeatingOffT);    
  Alarm.alarmRepeat(dowSunday,20,31,00, HeatingOffT);    
  //End of Heating off Timers  

}

// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(IPAddress& address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 		   
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket(); 
}


//const  long timeZoneOffset = 0L; // set this to the offset in seconds to your local time;
void synTime(){
  Time rtime = rtc.time();
  setTime(rtime.hr,rtime.min,rtime.sec,rtime.date,rtime.mon,rtime.yr); 

}

void getNtpTime()
{

  sendNTPpacket(timeServer);
  delay(1000);
  if ( Udp.available() ) {
    for(int i=0; i < 40; i++)
      Udp.read(); // ignore every field except the time
    const unsigned long seventy_years = 2208988800UL - adjustDst();        
    time_t t =  getUlong() -  seventy_years;  

    Time t2(year(t), month(t), day(t), hour(t), minute(t), second(t), weekday(t));
    rtc.time(t2);
    synTime();   
    //    setTime(t);
    //    return getUlong() -  seventy_years;      
  }
  //  return 0; // return 0 if unable to get the time
}
unsigned long getUlong()
{
  unsigned long ulong = (unsigned long)Udp.read() << 24;
  ulong |= (unsigned long)Udp.read() << 16;
  ulong |= (unsigned long)Udp.read() << 8;
  ulong |= (unsigned long)Udp.read();
  return ulong;
}


void GetTemps(){
  sensors.getAddress(NewTemp[99].address, 0);  
  NewTemp[99].temp = sensors.getTempC(NewTemp[99].address);

  for(int i=0; i< sensors2.getDeviceCount(); i++){
    sensors2.getAddress(NewTemp[i].address, i);
    NewTemp[i].temp = sensors2.getTempC(NewTemp[i].address);
  }
}
//
//void sendTemps(){
//  for(int i=0; i< sensors2.getDeviceCount(); i++){  
//     Mirf.setTADDR((byte *)"clock");
//    char * msgsend;
//    itoa(NewTemp[i].temp,msgsend,4);
////    sprintf(msgsend, "Temp:%i:%s",i, NewTemp[i].temp);    
//    transmit((String)msgsend);
//    delay(10); 
//  }
//}
//
//void transmit(String MSG){
//
//  String MSG2 ="*";
//  MSG2 += MSG;
//  MSG2 +="#";
//  int sections = MSG2.length() / 32;
//  // Serial.println(sections);
//  int c =0;
//  for(int i =0;i<sections +1;i++){
//
//    Serial.println(i);
//    String tmp = MSG2.substring(i*32,(i+1)*32);
//    char sendmsg[tmp.length()+1];
//    tmp.toCharArray(sendmsg,tmp.length() +1);
//    Serial.println(sendmsg);
//    Mirf.send((byte *)sendmsg);
//    while(Mirf.isSending()){
//    }
//
//  } 
//}

float CalcAvTemp(){
  float AvTemp =0;
  int count =0;
  int Devices = sensors2.getDeviceCount() + sensors.getDeviceCount()-1;
  for (int i=1; i< Devices;i++){
    if ( i ==5 || i ==2 || i==0){
      continue; 
    }
    AvTemp += NewTemp[i].temp;
    count++;
  } 
  return AvTemp / count;

}
String makeAddress(DeviceAddress deviceAddress)
{
  String newadd;
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) Serial.print("0");
    newadd += String(deviceAddress[i],HEX);
    return newadd;
    //    Serial.print(deviceAddress[i], HEX);
  }
}

int adjustDst()
{
  // last sunday of march
  int beginDSTDate=  (31 - (5* year() /4 + 4) % 7);
  //  Serial.println(beginDSTDate);
  int beginDSTMonth=3;
  //last sunday of october
  int endDSTDate= (31 - (5 * year() /4 + 1) % 7);
  //  Serial.println(endDSTDate);
  int endDSTMonth=10;
  // DST is valid as:
  if (((month() > beginDSTMonth) && (month() < endDSTMonth))
    || ((month() == beginDSTMonth) && (day() >= beginDSTDate)) 
    || ((month() == endDSTMonth) && (day() <= endDSTDate)))
    return 0;  // DST europe = utc +2 hour
  else return 3600; // nonDST europe = utc +1 hour
}














